#include <iostream>
#include <vector>
#include <cmath>
#include "../spline_functions.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

int main() {
    std::cout << "-------Problem 4: Testing B-3-spline == PP-3-spline-------" << std::endl;

    // 定义节点和系数
    std::vector<double> knots = {0, 0.4, 1.5, 2.6, 4};
    std::vector<double> coefficients;
    for (double knot : knots) {
        coefficients.push_back(sin(M_PI * knot * knot) + cos(knot));
    }

    // 创建周期边界条件三次样条对象
    PeriodicCubicSpline_p periodicSpline(knots, coefficients);
    PeriodicCubicSpline_B periodicSpline_B(3, knots, coefficients);

    // 创建自然三次样条对象
    NaturalSpline_p naturalSpline(knots, coefficients);
    NaturalSpline_B naturalSpline_B(3, knots, coefficients);

    // 创建完全三次样条对象
    ClampedCubicSpline_p clampedSpline(knots, coefficients, 1, M_PI);
    ClampedCubicSpline_B clampedSpline_B(3, knots, coefficients, 1, M_PI);

    // 定义要评估的点
    std::vector<double> points = {0.2, 1.35, 2, 3.7};

    // 评估样条函数在这些点的值
    std::cout << "---Part1. Testing PeriodicCubicSpline:" << std::endl;
    for (double x : points) {
        try {
            double value = periodicSpline.evaluate(x);
            std::cout << "PP Periodic cubic spline value at x = " << x << " is " << value << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "Error evaluating periodic cubic spline at x = " << x << ": " << e.what() << std::endl;
        }
    }
    for (double x : points) {
        try {
            double value = periodicSpline_B.evaluate(x);
            std::cout << "B Periodic cubic spline value at x = " << x << " is " << value << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "Error evaluating periodic cubic spline at x = " << x << ": " << e.what() << std::endl;
        }
    }
    std::cout << "---Part2. Testing NaturalSpline:" << std::endl;
    for (double x : points) {
        try {
            double value = naturalSpline.evaluate(x);
            std::cout << "PP Natural cubic spline value at x = " << x << " is " << value << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "Error evaluating natural cubic spline at x = " << x << ": " << e.what() << std::endl;
        }
    }
    for (double x : points) {
        try {
            double value = naturalSpline_B.evaluate(x);
            std::cout << "B Natural cubic spline value at x = " << x << " is " << value << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "Error evaluating natural cubic spline at x = " << x << ": " << e.what() << std::endl;
        }
    }
    std::cout << "---Part3. Testing ClampedCubicSpline:" << std::endl;
    for (double x : points) {
        try {
            double value = clampedSpline.evaluate(x);
            std::cout << "PP Clamped cubic spline value at x = " << x << " is " << value << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "Error evaluating clamped cubic spline at x = " << x << ": " << e.what() << std::endl;
        }
    }
    for (double x : points) {
        try {
            double value = clampedSpline_B.evaluate(x);
            std::cout << "B Clamped cubic spline value at x = " << x << " is " << value << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "Error evaluating clamped cubic spline at x = " << x << ": " << e.what() << std::endl;
        }
    }

    return 0;
}